Skip to content

Various extensions#23

Open
maximebuyse wants to merge 7 commits into
mainfrom
openmls-extensions
Open

Various extensions#23
maximebuyse wants to merge 7 commits into
mainfrom
openmls-extensions

Conversation

@maximebuyse

Copy link
Copy Markdown
Collaborator

No description provided.

@maximebuyse maximebuyse requested a review from abentkamp June 24, 2026 14:00

@abentkamp abentkamp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovely! I have a couple of comments: some missing tests, some opinons on Lean implementations of rust primitives, some questions...

Comment on lines 60 to +70
proptest! {
#[test]
fn test_clone(x in any::<u8>()) {
let model = x.inject();
prop_assert_eq!(model.clone(), model);
}

#[test]
fn test_clone_bool(x in any::<bool>()) {
prop_assert_eq!(crate::clone::Clone::clone(x), x);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing that inject is the identity on these types, but maybe we should be consistent?

Are there tests missing for all other integer types other than u8?

In one test, we use core's clone, in the other we use core model's clone. Shouldn't we use both in both tests?

Comment on lines +58 to +63
// Use the primitive length directly rather than `x.len()`: the latter
// extracts to a reference to `slice::Slice::len`, which (under
// `-core-models-lib`) Aeneas emits as an external-looking name with no
// dependency edge, producing a forward reference here (this `convert`
// module is extracted before `slice`).
if rust_primitives::slice::slice_length(x) == N {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like Claude felt a bit too chatty :-).

Does this need a comment at all? If so, I would write: "Use rust primitive instead of x.len() to avoid forward reference in Lean."

Comment on lines 261 to 265
#[test]
fn test_as_ref_identity(x in any::<u8>()) {
prop_assert_eq!(super::AsRef::as_ref(x.inject()), x);
fn test_as_ref_slice_identity(v in prop::collection::vec(any::<u8>(), 0..=8)) {
let s: &[u8] = &v[..];
prop_assert_eq!(super::AsRef::as_ref(s), s);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't a test for u8 good to have as well? Maybe too trivial?

Should we call inject? and apply as_ref on both sides?

Comment on lines +22 to +33
macro_rules! impl_hash_for_int {
($($t:ty),*) => {
$(
#[hax_lib::attributes]
impl Hash for $t {
fn hash<H: Hasher>(&self, mut h: H) -> H {
h.write(&[*self as u8]);
h
}
}
)*
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we implement this correctly? Should we establish some way of keeping track where we intentionally deviate from the official implementation?

Comment on lines 103 to 105
#[hax_lib::attributes]
#[cfg_attr(charon, aeneas::exclude)]
//#[cfg_attr(charon, aeneas::exclude)]
impl<T> Slice<T> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove instead of commenting out?

);
}

// ----- get_unchecked (in-bounds) -------------------------------------

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of tests missing here for the different Range* variants.

Comment on lines +84 to +86
ok (sub, fun ss => match Slice.update_subslice s ⟨b, e⟩ ss with
| .ok r => r
| _ => s)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using ⟨ s.val.setSlice! ..., by scalar_tac ⟩ might be more elegant here: Matching on a Result value inside the Result monad is a bit odd. But we would then have to check whether ss has the correct length.

I also suspect that what's implemented here is not the correct behavior for the case where ss has not the correct length? Or is this impossible to do in Rust?

@[rust_fun "rust_primitives::slice::slice_reverse"]
def rust_primitives.slice.slice_reverse
{T : Type} : Slice T → Result (Slice T) :=
fun s => ok ⟨ s.val.reverse, by have := s.property; simp [*] ⟩

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing by simp [s.property] would do as well?

Comment on lines +962 to +964
// =============================================================================
// div_ceil (unsigned)
// =============================================================================

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about signed?

Comment on lines +762 to +764
// ----- get_unchecked (in-bounds) ---------------------------------------------
// In-bounds is the only defined behaviour; the model projects like `index`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about get_mut and get_unchecked_mut? What about all the Range* variants?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants